package com.ndp.fb.walle.controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.ndp.ec.core.FbUserService;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.ErrorType;
import com.ndp.fb.model.business.vo.cache.result.EntrustAccountListVo;
import com.ndp.fb.model.business.vo.cache.result.EntrustAccountVo;
import com.ndp.fb.mq.api.service.schedulerservice.business.syncbusiness.SyncAccountResourceService;
import com.ndp.fb.rdb.api.AppInfoRdbService;
import com.ndp.fb.rdb.api.FbUserRdbService;
import com.ndp.fb.rdb.model.AppInfo;
import com.ndp.fb.rdb.model.BusinessManager;
import com.ndp.fb.rdb.model.EntrustAccountExt;
import com.ndp.fb.rdb.model.FbUser;
import com.ndp.fb.rdb.model.Pager;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.walle.business.BusinessManagerService;
import com.ndp.fb.walle.business.EntrustAccountService;
import com.ndp.fb.walle.business.FBOauthService;
import com.ndp.fb.walle.helper.TokenHelper;
import com.ndp.fb.walle.model.bo.entrustaccount.AccountOperateHistoryResult;
import com.ndp.fb.walle.model.bo.entrustaccount.ChangeAccountResult;
import com.ndp.fb.walle.model.vo.IdsVoParam;
import com.ndp.fb.walle.model.vo.OutputResult;
import com.ndp.fb.walle.model.vo.PageResult;
import com.ndp.fb.walle.model.vo.adpublishcondition.param.AccountFromConnParam;
import com.ndp.fb.walle.model.vo.entrustaccount.param.BusinessManagerParam;
import com.ndp.fb.walle.model.vo.entrustaccount.param.FbUserBusinessParam;
import com.ndp.fb.walle.util.ResponseUtils;

/**
 * Created by Mikey.zhaopeng on 2014/10/24 14:56.
 * Email mikey.zhao@ndpmedia.com
 */
@RequestMapping("/entrustaccounts")
@Controller
public class EntrustAccountController {
    private final org.slf4j.Logger LOG = LoggerFactory.getLogger(getClass());

    @Autowired
    private EntrustAccountService entrustAccountService;

    @Autowired
    private BusinessManagerService businessManagerService;

    @Autowired
    private FBOauthService fbOauthService;

    @Autowired
    private TokenHelper tokenHelper;

    @Reference
    private FbUserService fbUserService;

    @Reference
    private FbUserRdbService fbUserRdbService;

    @Reference
    private AppInfoRdbService appInfoRdbService;

    @Reference
    private SyncAccountResourceService syncAccountResourceService;


    /**
     * 根据Bm获取账号
     * @param param
     * @param request
     * @return
     */
    @RequestMapping("entrustAccountList")
    @ResponseBody
    public ResponseEntity<String> entrustAccountList(@RequestParam(value = "param", required = true) String param, HttpServletRequest request) {
        ErrorType errorType = null;
        Map data = new HashMap();
        try {
            // 获取bm
            FbUser fbUser = fbUserService.getFbUser(this.getUserId(request));
            if (fbUser == null) { // 如果没有bm,则给前台传递一个 Facebook 的链接
                data = new HashMap();
                errorType = ErrorType.NEED_ADD_BUSINESS_MANAGER_ACCOUNT;
                AppInfo appInfo = appInfoRdbService.getAppInfo();
                String fbRedirect = tokenHelper.getFacebookCode(appInfo);
                data.put("addAccountLink", fbRedirect);
            } else {
                BusinessManagerParam baseVoParam = JSON.parseObject(param, BusinessManagerParam.class);
                // 查询列表
                int sizeNo = baseVoParam.getPSize() == null ? CommonConstants.DEFAULT_PAGE_SIZE_100 : baseVoParam.getPSize();
                int firstResult = baseVoParam.getCPage() == null ? 0 : (baseVoParam.getCPage() - 1) * sizeNo;

                Pager<EntrustAccountExt> pageEntrustAccounts = entrustAccountService.findEntrustAccountsPagerByUserId(fbUser.getUserId(), baseVoParam.getBusinessId(), firstResult, sizeNo);

                if (pageEntrustAccounts == null || pageEntrustAccounts.getResultList() == null || pageEntrustAccounts.getResultList().size() == 0) {

                    data = new HashMap();
                    // 返回BM 和 帐号列表
                    fbUser.setAccessToken("");
                    data.put("fbUser", fbUser);

                    // 计算分页结果
                    long tSize = 0;
                    float nrOfPages = (float) tSize / sizeNo;
                    int tPage = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages);
                    PageResult pageResult = new PageResult(tPage, baseVoParam.getCPage(), baseVoParam.getPSize(), tSize);

                    data.put("EntrustAccounts", null);
                    data.put("paginator", pageResult);

                } else {
                    data = new HashMap();
                    // 返回BM 和 帐号列表
                    fbUser.setAccessToken("");
                    data.put("fbUser", fbUser);

                    // 计算分页结果
                    long tSize = pageEntrustAccounts.getTotalSize();
                    float nrOfPages = (float) tSize / sizeNo;
                    int tPage = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages);
                    PageResult pageResult = new PageResult(tPage, baseVoParam.getCPage(), baseVoParam.getPSize(), tSize);

                    data.put("EntrustAccounts", pageEntrustAccounts.getResultList());
                    data.put("paginator", pageResult);
                }
            }
        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
            LOG.error(e.getMessage(), e);
        }

        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    /**
     * 获取当前用户的Bm
     * @param request
     * @return
     */
    @RequestMapping("businessManagers")
    @ResponseBody
    public ResponseEntity<String> businessManagers(HttpServletRequest request) {

        ErrorType errorType = null;
        Map data = new HashMap();
        try {
            // 获取bm
            String userId = this.getUserId(request);
            FbUser fbUser = fbUserService.getFbUser(userId);
            if (fbUser == null) { // 如果没有bm,则给前台传递一个 Facebook 的链接
                data = this.getOauthAppResutlData();
                 errorType = ErrorType.NEED_ADD_BUSINESS_MANAGER_ACCOUNT;
            } else {
                boolean isInvalid = fbUserRdbService.getIsInvalidByUserId(userId);//判断账号是否失效
                if (isInvalid) {
                    data = this.getOauthAppResutlData();
                     errorType = ErrorType.NEED_ADD_BUSINESS_MANAGER_ACCOUNT;
                } else {
                    List<BusinessManager> businessManagers = businessManagerService.findByUserId(fbUser.getUserId());
                    fbUser.setAccessToken("");
                    data.put("fbUser", fbUser);
                    data.put("businessmanagers", businessManagers);
                }
            }
        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
            LOG.error(e.getMessage(), e);
        }

        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }
    /**
     * 获取当前用户的Bm
     * @param request
     * @return
     */
    @RequestMapping("businessManagersAdmin")
    @ResponseBody
    public ResponseEntity<String> businessManagersAdmin(HttpServletRequest request) {

        ErrorType errorType = null;
        Map data = new HashMap();
        try {
            // 获取bm
            String userId = this.getUserId(request);
            FbUser fbUser = fbUserService.getFbUser(userId);
            if (fbUser == null) { // 如果没有bm,则给前台传递一个 Facebook 的链接
                data = this.getOauthAppResutlData();
                 errorType = ErrorType.NEED_ADD_BUSINESS_MANAGER_ACCOUNT;
            } else {
                boolean isInvalid = fbUserRdbService.getIsInvalidByUserId(userId);//判断账号是否失效
                if (isInvalid) {
                    data = this.getOauthAppResutlData();
                     errorType = ErrorType.NEED_ADD_BUSINESS_MANAGER_ACCOUNT;
                } else {
                    List<BusinessManager> businessManagers = businessManagerService.findByUserId(fbUser.getUserId(),"ADMIN");
                    fbUser.setAccessToken("");
                    data.put("fbUser", fbUser);
                    data.put("businessmanagers", businessManagers);
                }
            }
        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
            LOG.error(e.getMessage(), e);
        }

        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }
    
    /**
     * 由单个应用id找到 广告账号
     * @param param
     * @param request
     * @return
     */
    @RequestMapping("getAccounts")
    @ResponseBody
    public ResponseEntity<String> getAccounts(@RequestParam(value = "param", required = true) String param, HttpServletRequest request) {

        LOG.info("EntrustAccountController getAccounts() begin.");
        ErrorType errorType = null;
        EntrustAccountListVo entrustAccountListVo = null;
        try {
            User user = (User) request.getSession().getAttribute("user");

            AccountFromConnParam accountFromConnParam = JSON.parseObject(param, AccountFromConnParam.class);
            List<EntrustAccountExt> entrustAccounts = entrustAccountService.findEntrustAccountsByfbConnectionObjectIdAndUserId(accountFromConnParam.getConnObjId(), user.getTicket());
            if (ListUtil.isEmpty(entrustAccounts)) {
                entrustAccountListVo = new EntrustAccountListVo();
            } else {
                entrustAccountListVo = getEntrustAccountVo(entrustAccounts);
            }
        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
            LOG.error(e.getMessage(), e);
        }

        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, entrustAccountListVo);
        LOG.info("EntrustAccountController getAccounts() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSON(outputResult).toString());
    }

    private EntrustAccountListVo getEntrustAccountVo(List<EntrustAccountExt> entrustAccounts) {
        List<EntrustAccountVo> voList = new ArrayList<>();
        EntrustAccountListVo entrustAccountListVo = new EntrustAccountListVo();
        EntrustAccountVo entrustAccountVo;
        Set<Long> ids = new HashSet<>();
        for (EntrustAccountExt entrustAccount : entrustAccounts) {
            if (ids.contains(entrustAccount.getFbAccountId())) {
                continue;
            }
            ids.add(entrustAccount.getFbAccountId());
            String timezoneStr = null;
            int offset = Calendar.getInstance(TimeZone.getTimeZone(entrustAccount.getTimezone())).get(Calendar.ZONE_OFFSET) / 1000 / 60 / 60;
            if (offset < 0) {
                timezoneStr = ("GMT-" + (Math.abs(offset) > 9 ? ("" + Math.abs(offset)) : ("0" + Math.abs(offset))) + ":00");
            } else {
                timezoneStr = ("GMT+" + (Math.abs(offset) > 9 ? ("" + Math.abs(offset)) : ("0" + Math.abs(offset))) + ":00");
            }
            String timezoneOffset = String.valueOf(Calendar.getInstance(TimeZone.getTimeZone(entrustAccount.getTimezone())).get(Calendar.ZONE_OFFSET) / 1000 / 60);
            entrustAccountVo = new EntrustAccountVo();
            entrustAccountVo.setId(entrustAccount.getId());
            String displayName = StringUtils.isEmpty(entrustAccount.getEmail()) ? (StringUtils.isEmpty(entrustAccount.getName()) ? (entrustAccount.getFbAccountId() + "") : entrustAccount.getName()) : entrustAccount.getEmail();
            entrustAccountVo.setDisplayName(displayName);
            entrustAccountVo.setFbAccountId(entrustAccount.getFbAccountId());
            entrustAccountVo.setRole(entrustAccount.getRole());
            entrustAccountVo.setBusinessId(entrustAccount.getFbBusinessId());
            entrustAccountVo.setTimezone(entrustAccount.getTimezone());
            entrustAccountVo.setOffset(offset);
            entrustAccountVo.setTimezoneOffset(timezoneOffset);
            entrustAccountVo.setTimezoneStr(timezoneStr);
            voList.add(entrustAccountVo);
        }

        entrustAccountListVo.setAccounts(voList);
        return entrustAccountListVo;
    }

    /**
     * 同步账号
     * @param request
     * @return
     */
    @RequestMapping(value = "syncEntrustAccount", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<String> syncEntrustAccount(@RequestParam(value = "param", required = true) String param,HttpServletRequest request) {

        ErrorType errorType = null;
        Map data = new HashMap();
        try {
            // 获取bm
            String userId = this.getUserId(request);
            FbUser fbUser = fbUserService.getFbUser(userId);
            if (fbUser == null) {
                // 如果没有bm,则给前台传递一个 Facebook 的链接
                data = new HashMap();
                errorType = ErrorType.NEED_ADD_BUSINESS_MANAGER_ACCOUNT;
                AppInfo appInfo = appInfoRdbService.getAppInfo();
                String fbRedirectri = tokenHelper.getFacebookCode(appInfo);
                data.put("addAccountLink", fbRedirectri);
            } else {

                IdsVoParam entrustAccountVoIds = JSON.parseObject(param, IdsVoParam.class);
                List<EntrustAccountExt> facebookEntrustAccounts = fbOauthService.paramToEntrustAccount(entrustAccountVoIds.getNewAddIds(), fbUser.getAccessToken());

                // 开始同步
                boolean result = fbOauthService.syncNewEntrustInformation(fbUser.getUserId(), facebookEntrustAccounts, entrustAccountVoIds.getNewAddIds());
                if (!result) {
                    errorType = ErrorType.AD_ACCOUNTS_SYNC_FAILURE;
                }

                data.put("fbUser", fbUser);
            }

        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
            LOG.error(e.getMessage(), e);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    private String getUserId(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        return user.getTicket() + "";
    }


    /**
     * 账号同步-账号列表变化
     * @param request
     * @return
     */
    @RequestMapping(value = "changeAccountList", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<String> changeAccountList(HttpServletRequest request) {
        ErrorType errorType = null;
        Map data = new HashMap();
        data.put("success", "true");
        try {
            // 获取bm
            ChangeAccountResult result = fbOauthService.getChangeEntrustAccount(this.getUserId(request));
            data.put("recycleAccounts", result.getRecycleAccounts());
            data.put("appendAccounts", result.getAppendAccounts());
            data.put("changeAccounts", result.getUpdateAccounts());
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            data.put("success", "false");
            errorType = ErrorType.LIST_RECYCLE_ACCOUNT_FAIL;
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    /**
     * 账号操作记录
     * @param request
     * @return
     */
    @RequestMapping(value = "accountOperateHistoryList", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<String> accountOperateHistoryList(HttpServletRequest request) {
        ErrorType errorType = null;
        Map data = null;
        try {
            User user = (User) request.getSession().getAttribute("user");
            data = new HashMap();
            data.put("success", "true");
            List<AccountOperateHistoryResult> accountOperateHistoryResultList = entrustAccountService.getAccountOperateHistoryList(user);
            data.put("history", accountOperateHistoryResultList);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    /**
     * 解除账号绑定
     * @param param
     * @param request
     * @return
     */
    @RequestMapping("unBindEntrustAccount")
    @ResponseBody
    public ResponseEntity<String> unBindEntrustAccount(@RequestParam(value = "param", required = true) String param, HttpServletRequest request) {
        ErrorType errorType = null;
        User user = (User) request.getSession().getAttribute("user");
        FbUserBusinessParam fbUserBusinessParam = JSON.parseObject(param, FbUserBusinessParam.class);
        if(fbUserBusinessParam == null || fbUserBusinessParam.getEntrustAccountId() == null || fbUserBusinessParam.getFbBussinessId() == null)
            errorType = ErrorType.PARAM_EXCEPTION;
        Map data = new HashMap();
        LOG.info("entrust account id:" + fbUserBusinessParam.getEntrustAccountId());
        LOG.info("business id:" + fbUserBusinessParam.getFbBussinessId());
        try {
            boolean result = entrustAccountService.unBindEntrustAccount(fbUserBusinessParam.getEntrustAccountId(), fbUserBusinessParam.getFbBussinessId(), user);
            if (result) {
                data.put("success", "true");
            } else {
                data.put("success", "false");
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    /**
     * 得到授权链接等信息
     *
     * @return
     */
    private Map getOauthAppResutlData() {
        Map data = new HashMap();
        AppInfo appInfo = appInfoRdbService.getAppInfo();
        String fbRedirect = tokenHelper.getFacebookCode(appInfo);
        data.put("addAccountLink", fbRedirect);
        return data;
    }
}
